#include "CryptoUtils.h"

#include <algorithm>
#include <cstring>
#include <stdexcept>

#include "rmd128.h"

#define F(x, y, z) ((x) ^ (y) ^ (z))
#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define H(x, y, z) (((x) | ~(y)) ^ (z))
#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))

// RIPEMD128哈希函数实现
std::vector<uint8_t> CryptoUtils::ripemd128(const std::vector<uint8_t>& data) {
    // 组合最终哈希值
    std::vector<uint8_t> result(16, 0);
    rmd128_t* c;
    if (!(c = (rmd128_t*)std::malloc(rmd128tsize()))) {
        return result;
    }
    rmd128init(c);
    rmd128update(c, data.data(), data.size());
    rmd128final(c, result.data());
    std::free(c);

    return result;
}

// Salsa20加密/解密实现（8轮）
std::vector<uint8_t> CryptoUtils::salsa20_encrypt(
    const std::vector<uint8_t>& data, const std::vector<uint8_t>& key) {
    return salsa20_decrypt(data, key);  // Salsa20加密和解密使用相同的函数
}

std::vector<uint8_t> CryptoUtils::salsa20_decrypt(
    const std::vector<uint8_t>& data, const std::vector<uint8_t>& key) {
    if (key.size() != 32) {
        throw std::runtime_error("Salsa20 key must be 32 bytes");
    }

    std::vector<uint8_t> result(data.size());
    uint32_t state[16];
    uint8_t key_stream[64];

    // 初始化状态
    state[0] = 0x61707865;  // "expa"
    state[1] = *reinterpret_cast<const uint32_t*>(key.data());
    state[2] = *reinterpret_cast<const uint32_t*>(key.data() + 4);
    state[3] = *reinterpret_cast<const uint32_t*>(key.data() + 8);
    state[4] = *reinterpret_cast<const uint32_t*>(key.data() + 12);
    state[5] = 0x3320646e;  // "nd 3"
    state[6] = 0x79622d32;  // "2-by"
    state[7] = 0x6b206574;  // "te k"
    state[8] = *reinterpret_cast<const uint32_t*>(key.data() + 16);
    state[9] = *reinterpret_cast<const uint32_t*>(key.data() + 20);
    state[10] = *reinterpret_cast<const uint32_t*>(key.data() + 24);
    state[11] = *reinterpret_cast<const uint32_t*>(key.data() + 28);
    state[12] = 0;  // 块计数器（简单实现中设为0）
    state[13] = 0;
    state[14] = 0;
    state[15] = 0;

    // 生成密钥流并与数据异或
    for (size_t i = 0; i < data.size(); i += 64) {
        // 复制状态用于轮操作
        uint32_t work_state[16];
        std::memcpy(work_state, state, sizeof(state));

        // 执行8轮操作
        for (int r = 0; r < 8; r += 2) {
            // 列混合
            work_state[4] ^= ROTL(work_state[0] + work_state[12], 7);
            work_state[8] ^= ROTL(work_state[4] + work_state[0], 9);
            work_state[12] ^= ROTL(work_state[8] + work_state[4], 13);
            work_state[0] ^= ROTL(work_state[12] + work_state[8], 18);

            work_state[9] ^= ROTL(work_state[5] + work_state[1], 7);
            work_state[13] ^= ROTL(work_state[9] + work_state[5], 9);
            work_state[1] ^= ROTL(work_state[13] + work_state[9], 13);
            work_state[5] ^= ROTL(work_state[1] + work_state[13], 18);

            work_state[14] ^= ROTL(work_state[10] + work_state[6], 7);
            work_state[2] ^= ROTL(work_state[14] + work_state[10], 9);
            work_state[6] ^= ROTL(work_state[2] + work_state[14], 13);
            work_state[10] ^= ROTL(work_state[6] + work_state[2], 18);

            work_state[3] ^= ROTL(work_state[15] + work_state[11], 7);
            work_state[7] ^= ROTL(work_state[3] + work_state[15], 9);
            work_state[11] ^= ROTL(work_state[7] + work_state[3], 13);
            work_state[15] ^= ROTL(work_state[11] + work_state[7], 18);

            // 行混合
            work_state[1] ^= ROTL(work_state[0] + work_state[3], 7);
            work_state[2] ^= ROTL(work_state[1] + work_state[0], 9);
            work_state[3] ^= ROTL(work_state[2] + work_state[1], 13);
            work_state[0] ^= ROTL(work_state[3] + work_state[2], 18);

            work_state[6] ^= ROTL(work_state[5] + work_state[4], 7);
            work_state[7] ^= ROTL(work_state[6] + work_state[5], 9);
            work_state[4] ^= ROTL(work_state[7] + work_state[6], 13);
            work_state[5] ^= ROTL(work_state[4] + work_state[7], 18);

            work_state[11] ^= ROTL(work_state[10] + work_state[9], 7);
            work_state[8] ^= ROTL(work_state[11] + work_state[10], 9);
            work_state[9] ^= ROTL(work_state[8] + work_state[11], 13);
            work_state[10] ^= ROTL(work_state[9] + work_state[8], 18);

            work_state[12] ^= ROTL(work_state[15] + work_state[14], 7);
            work_state[13] ^= ROTL(work_state[12] + work_state[15], 9);
            work_state[14] ^= ROTL(work_state[13] + work_state[12], 13);
            work_state[15] ^= ROTL(work_state[14] + work_state[13], 18);
        }

        // 将初始状态添加到工作状态
        for (int j = 0; j < 16; ++j) {
            work_state[j] += state[j];
        }

        // 将工作状态转换为密钥流
        for (int j = 0; j < 16; ++j) {
            key_stream[j * 4] = (work_state[j] >> 24) & 0xff;
            key_stream[j * 4 + 1] = (work_state[j] >> 16) & 0xff;
            key_stream[j * 4 + 2] = (work_state[j] >> 8) & 0xff;
            key_stream[j * 4 + 3] = work_state[j] & 0xff;
        }

        // 增加块计数器
        state[12] += 1;
        if (state[12] == 0) {
            state[13] += 1;
        }

        // 使用密钥流加密当前块
        size_t block_size = std::min(static_cast<size_t>(64), data.size() - i);
        for (size_t j = 0; j < block_size; ++j) {
            result[i + j] = data[i + j] ^ key_stream[j];
        }
    }

    return result;
}

// Fast解密实现（XOR方式）
std::vector<uint8_t> CryptoUtils::fast_decrypt(
    const std::vector<uint8_t>& data, const std::vector<uint8_t>& key) {
    if (key.empty()) {
        return data;
    }
    uint8_t previous = 0x36;

    std::vector<uint8_t> result(data.size());

    // 对每个字节进行XOR解密
    for (size_t i = 0; i < data.size(); i++) {
        auto t = (data[i] >> 4 | data[i] << 4) & 0xff;
        t = t ^ previous ^ (i & 0xff) ^ key[i % key.size()];
        previous = data[i];
        result.at(i) = t;
    }

    return result;
}

// XXH64哈希函数实现
std::vector<uint8_t> CryptoUtils::xxh64_digest(
    const std::vector<uint8_t>& data) {
    // 简化版XXH64实现
    // 实际应用中建议使用官方XXH库
    uint64_t hash = 0x0123456789abcdef;

    for (size_t i = 0; i < data.size(); ++i) {
        hash += static_cast<uint64_t>(data[i]) << ((i % 8) * 8);
        hash *= 0x9e3779b97f4a7c15;  // 黄金比例数
    }

    // 将哈希值转换为字节数组
    std::vector<uint8_t> result(8);
    for (int i = 0; i < 8; ++i) {
        result[i] = (hash >> (i * 8)) & 0xff;
    }

    return result;
}
